/* Copyright (c) 2006-2012, DNSPod Inc.
 * All rights reserved.
  
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 * The views and conclusions contained in the software and documentation are those
 * of the authors and should not be interpreted as representing official policies,
 * either expressed or implied, of the FreeBSD Project.
 */ 


#ifndef _AUTHOR_H
#define _AUTHOR_H

#define _GNU_SOURCE

#include "io.h"
#include <sys/ipc.h>
#include <sys/shm.h>

enum {
    FETCHER_NUM = 1,
    SERVER_PORT = 53,
};


enum {
    QUIZZER_NUM = 1,
};


enum {
    NEW_QUERY = 0,
    PROCESS_QUERY = 1,
    TTL_UPDATE = 3,
    SHM_KEY = 38899,
};


#define SRV_ADDR ("0.0.0.0")

enum {
    //MAX_TRY_TIMES = 15,
    REFRESH_INTERVAL = 10,
/*    AUTH_DB_NUM = 101,*/
    BIG_MEM_STEP = 2000,
    RANDOM_SIZE = 3000,
/*    ID_SPACE = 60000,*/
    AUTH_DATA_LEN = 65528,      //for meta data
    EP_TCP_FDS = 65530,
};


enum {
    LIST_SPACE = 10000,
};

#define OPT_LEN 9U                      /* Length of the NSD EDNS response record minus 2 */
#define OPT_RDATA 2                     /* holds the rdata length comes after OPT_LEN */
/*#define OPT_HDR 4U                      / * NSID opt header length * /*/
/*#define NSID_CODE       3               / * nsid option code * /*/
/*#define DNSSEC_OK_MASK  0x8000U         / * do bit mask * /*/

 typedef struct  {
    int ret;
    uchar domain[256];
}eptcpfds;

 typedef struct _server  server;




 typedef struct  author {
    int audp,                   //read and send auth server, private
     cudp,                      //send to client, share with other author
     idx;
     server *s;
    pthread_spinlock_t lock;       //protect list above
/*     qoutinfo *list[LIST_SPACE];*/
    //statis
/*    int qnum;*/
    int response;
/*    int qidx;*/
/*    int timex;*/
    ////
    // list *el;
    int bdepfd;
     log_info *loginfo;
  /*  pthread_spinlock_t dblock[AUTH_DB_NUM];        //protect db in disk*/
    uchar databuffer[AUTH_DATA_LEN];
    uchar randombuffer[RANDOM_SIZE];
    uchar tmpbuffer[BIG_MEM_STEP];
    uchar tdbuffer[256];
    uchar tempbuffer[IP_DATA_LEN];
    uchar dmbuffer[512];
    uchar ipbuffer[512];
    struct epoll_event e[BACK_EVENT];
    int rndidx;                 //no lock
  /*  int dataidx;                //no lock*/
    uchar ip[IP_DATA_LEN];      //shared by all qoutinfos
     eptcpfds eptcpfds[EP_TCP_FDS];
/*    uint rdb;                   //records in db*/
/*    int ddbefore;*/
/*    int underattack;*/
    int tcpinuse;
     htable_t *fwd;
     htable_t *ds;
    int dupbefore;              //only used in main thread
    int limits;                 //only used in main thread
    int hsidx;
    //statistics
/*    uint quizz;*/
/*    uint drop;*/
/*    uint timeout;*/
    int start, end;
}author;


 typedef struct  {
    int idx;
     server *s;
     msgcache *mc;
/*     list *el;*/
     log_info *loginfo;
/*    uchar originbuffer[AUTH_DATA_LEN];*/
    uchar tdbuffer[256];
    uchar databuffer[AUTH_DATA_LEN];
/*    uchar cbbuffer[512];*/
/*    int dataidx;*/
/*    int qidx;*/
    //statistics
    uint64_t pkg;
    uint64_t send;
    uint64_t miss;
}fetcher;


struct _server {
	 ushort nquizzer, nfetcher;
	 int p53udp, p53tcp;             //out udp
	 fetcher *fetchers;
	 author *authors;
	 list eventlist;
	 htable_t *datasets;
	 htable_t *nstables;
	 htable_t *forward;
	 // htable *rootz;
	 htable_t *qlist;       //same domain same type only query once.
	 ulong pkg;
	 uchar logpath[255];
/*	 ulong recordsindb;*/
	 rbtree *ttlexp;
	 //pthread_mutex_t lock;//protect ttlexp
	 uint16_t refreshflag;
	 time_t lastrefresh;
	 int is_forward;
 };


 server *global_serv;
char *g_nameservers[2];

#define MAX_CPU_NUM 65
 typedef struct  {
    unsigned long query_num[9];
}hread_query_info;


 typedef struct  {
    int thread_num;
    int log_flag;
	hread_query_info query_info[MAX_CPU_NUM];
}global_query_info;

 global_query_info *global_out_info;
int query_type_map[256];

typedef struct  {
    uint len;
    uint type;
    union {
        int fd;
         struct sockaddr_in addr;
    };
}seninfo;


void *run_quizzer(void *);
int run_fetcher( fetcher *f);
int write_back_to_client(mbuf_type *mbuf, uchar *, int);
int global_cron( server *);
/*int find_from_db( baseinfo *qi,  fetcher *f);*/

#endif
